@burtson-labs/bandit-engine 2.0.136 → 2.0.138

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  chat_default
3
- } from "./chunk-72TR4XAJ.mjs";
3
+ } from "./chunk-LDGJKNI4.mjs";
4
4
  import "./chunk-ONQMRE2G.mjs";
5
5
  import "./chunk-BVYSGIWG.mjs";
6
6
  import "./chunk-K2JGFKEB.mjs";
@@ -13,4 +13,4 @@ import "./chunk-BJTO5JO5.mjs";
13
13
  export {
14
14
  chat_default as default
15
15
  };
16
- //# sourceMappingURL=chat-AIQIJCAR.mjs.map
16
+ //# sourceMappingURL=chat-VBE333NU.mjs.map
@@ -1647,6 +1647,8 @@ ${sanitize(
1647
1647
  const hasFeedbackAction = isFeedbackEnabled && isMobile;
1648
1648
  const hasSttAction = isSTTAvailable && !isVoiceModeEnabled;
1649
1649
  const hasVoicePickerAction = isMobile && isTTSAvailable && availableVoices.length > 0;
1650
+ const hasComposeContent = !!inputValue.trim() || pastedImages.length > 0 || fileInputs.length > 0;
1651
+ const showSendButton = streamingActive || hasComposeContent || !isVoiceModeEligible;
1650
1652
  const hasSecondaryActions = isMobile && (hasAttachmentAction || hasMemoryAction || hasFeedbackAction || hasSttAction || hasVoicePickerAction);
1651
1653
  useEffect4(() => {
1652
1654
  if (!isMobile || !hasSecondaryActions) {
@@ -1711,6 +1713,33 @@ ${sanitize(
1711
1713
  if (!hasSttAction) return null;
1712
1714
  return /* @__PURE__ */ jsx9(Box6, { sx: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx9(transcriber_default, { onTranscriptionCompleted: handleTranscriptionCompleted }) }, key ?? "stt");
1713
1715
  };
1716
+ const renderVoiceModeButton = (key) => /* @__PURE__ */ jsx9(
1717
+ Tooltip2,
1718
+ {
1719
+ title: !isVoiceModeEnabled ? "Enable voice mode" : voiceStatus === "error" ? voiceError || "Voice mode error" : voiceStatus === "processing" ? "Transcribing your speech" : voiceStatus === "recording" ? "Recording - click to stop" : voiceStatus === "initializing" ? "Preparing microphone" : "Listening - click to turn off",
1720
+ children: /* @__PURE__ */ jsx9(
1721
+ IconButton5,
1722
+ {
1723
+ onClick: toggleVoiceMode,
1724
+ sx: {
1725
+ width: sendIconSize,
1726
+ height: sendIconSize,
1727
+ borderRadius: "50%",
1728
+ bgcolor: isVoiceModeEnabled ? alpha3(theme.palette.error.main, theme.palette.mode === "dark" ? 0.45 : 0.3) : fileText,
1729
+ color: isVoiceModeEnabled ? theme.palette.common.white : fileIconBg,
1730
+ boxShadow: isVoiceModeEnabled && voiceStatus === "recording" ? `0 0 0 2px ${alpha3(theme.palette.error.main, 0.25)}` : "none",
1731
+ transform: isVoiceModeEnabled && voiceStatus === "recording" ? "scale(1.05)" : "none",
1732
+ transition: "transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease",
1733
+ "&:hover": {
1734
+ bgcolor: isVoiceModeEnabled ? alpha3(theme.palette.error.main, theme.palette.mode === "dark" ? 0.55 : 0.38) : hoverBadgeBackground
1735
+ }
1736
+ },
1737
+ children: !isVoiceModeEnabled ? /* @__PURE__ */ jsx9(GraphicEqIcon, { fontSize: "small" }) : voiceStatus === "processing" || voiceStatus === "initializing" ? /* @__PURE__ */ jsx9(CircularProgress2, { size: 18, sx: { color: theme.palette.common.white } }) : voiceStatus === "error" ? /* @__PURE__ */ jsx9(HearingDisabledIcon, { fontSize: "small", sx: { color: theme.palette.error.light } }) : voiceStatus === "recording" ? /* @__PURE__ */ jsx9(GraphicEqIcon, { fontSize: "small", sx: { color: theme.palette.error.light } }) : /* @__PURE__ */ jsx9(GraphicEqIcon, { fontSize: "small", sx: { color: theme.palette.common.white } })
1738
+ }
1739
+ )
1740
+ },
1741
+ key ?? "voice-mode"
1742
+ );
1714
1743
  const renderVoicePickerButton = (key) => {
1715
1744
  if (!hasVoicePickerAction) return null;
1716
1745
  return /* @__PURE__ */ jsx9(Tooltip2, { title: `Voice: ${selectedVoice ? toTitleCase(selectedVoice.split("-")[1] ?? selectedVoice) : "Default"}`, children: /* @__PURE__ */ jsx9(
@@ -1958,51 +1987,22 @@ ${sanitize(
1958
1987
  minHeight: primaryIconSize
1959
1988
  },
1960
1989
  children: [
1961
- isVoiceModeEligible && /* @__PURE__ */ jsxs6(Fragment5, { children: [
1962
- /* @__PURE__ */ jsx9(
1963
- Tooltip2,
1964
- {
1965
- title: !isVoiceModeEnabled ? "Enable voice mode" : voiceStatus === "error" ? voiceError || "Voice mode error" : voiceStatus === "processing" ? "Transcribing your speech" : voiceStatus === "recording" ? "Recording - click to stop" : voiceStatus === "initializing" ? "Preparing microphone" : "Listening - click to turn off",
1966
- children: /* @__PURE__ */ jsx9(
1967
- IconButton5,
1968
- {
1969
- onClick: toggleVoiceMode,
1970
- sx: {
1971
- width: primaryIconSize,
1972
- height: primaryIconSize,
1973
- borderRadius: "50%",
1974
- bgcolor: isVoiceModeEnabled ? alpha3(theme.palette.error.main, theme.palette.mode === "dark" ? 0.45 : 0.3) : badgeBackground,
1975
- color: isVoiceModeEnabled ? theme.palette.common.white : fileText,
1976
- boxShadow: isVoiceModeEnabled && voiceStatus === "recording" ? `0 0 0 2px ${alpha3(theme.palette.error.main, 0.25)}` : "none",
1977
- transform: isVoiceModeEnabled && voiceStatus === "recording" ? "scale(1.05)" : "none",
1978
- transition: "transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease",
1979
- "&:hover": {
1980
- bgcolor: isVoiceModeEnabled ? alpha3(theme.palette.error.main, theme.palette.mode === "dark" ? 0.55 : 0.38) : hoverBadgeBackground
1981
- }
1982
- },
1983
- children: !isVoiceModeEnabled ? /* @__PURE__ */ jsx9(GraphicEqIcon, { fontSize: "small", sx: { color: theme.palette.mode === "dark" ? fileText : theme.palette.text.secondary } }) : voiceStatus === "processing" || voiceStatus === "initializing" ? /* @__PURE__ */ jsx9(CircularProgress2, { size: 18, sx: { color: fileText } }) : voiceStatus === "error" ? /* @__PURE__ */ jsx9(HearingDisabledIcon, { fontSize: "small", sx: { color: theme.palette.error.light } }) : voiceStatus === "recording" ? /* @__PURE__ */ jsx9(GraphicEqIcon, { fontSize: "small", sx: { color: theme.palette.error.light } }) : /* @__PURE__ */ jsx9(GraphicEqIcon, { fontSize: "small", sx: { color: theme.palette.common.white } })
1984
- }
1985
- )
1986
- }
1987
- ),
1988
- !isMobile && isVoiceModeEnabled && /* @__PURE__ */ jsx9(
1989
- Typography3,
1990
- {
1991
- variant: "caption",
1992
- sx: {
1993
- color: voiceStatus === "error" ? theme.palette.error.main : voiceStatus === "processing" ? theme.palette.warning.main : fileText,
1994
- maxWidth: 240,
1995
- overflow: "hidden",
1996
- textOverflow: "ellipsis",
1997
- whiteSpace: "nowrap"
1998
- },
1999
- children: voiceStatus === "error" ? voiceError || "Voice mode unavailable" : voiceStatus === "initializing" ? "Starting voice mode..." : voiceStatus === "recording" ? "Recording..." : voiceStatus === "processing" ? "Transcribing..." : voiceLastTranscript ? `Heard: "${voiceLastTranscript.length > 60 ? `${voiceLastTranscript.slice(0, 57)}...` : voiceLastTranscript}"` : "Listening..."
2000
- }
2001
- )
2002
- ] }),
2003
1990
  !isMobile && renderAttachmentButton("attach-inline"),
2004
1991
  !isMobile && renderMemoryButton("memory-inline"),
2005
- !isMobile && renderSttButton("stt-inline"),
1992
+ !isMobile && isVoiceModeEligible && isVoiceModeEnabled && /* @__PURE__ */ jsx9(
1993
+ Typography3,
1994
+ {
1995
+ variant: "caption",
1996
+ sx: {
1997
+ color: voiceStatus === "error" ? theme.palette.error.main : voiceStatus === "processing" ? theme.palette.warning.main : fileText,
1998
+ maxWidth: 240,
1999
+ overflow: "hidden",
2000
+ textOverflow: "ellipsis",
2001
+ whiteSpace: "nowrap"
2002
+ },
2003
+ children: voiceStatus === "error" ? voiceError || "Voice mode unavailable" : voiceStatus === "initializing" ? "Starting voice mode..." : voiceStatus === "recording" ? "Recording..." : voiceStatus === "processing" ? "Transcribing..." : voiceLastTranscript ? `Heard: "${voiceLastTranscript.length > 60 ? `${voiceLastTranscript.slice(0, 57)}...` : voiceLastTranscript}"` : "Listening..."
2004
+ }
2005
+ ),
2006
2006
  isMobile && hasSecondaryActions && /* @__PURE__ */ jsx9(
2007
2007
  IconButton5,
2008
2008
  {
@@ -2058,7 +2058,9 @@ ${sanitize(
2058
2058
  ),
2059
2059
  /* @__PURE__ */ jsxs6(Box6, { sx: { display: "flex", alignItems: "center", gap: isMobile ? 0.6 : 1 }, children: [
2060
2060
  !isMobile && /* @__PURE__ */ jsx9(engine_picker_default, {}),
2061
- /* @__PURE__ */ jsx9(Tooltip2, { title: isStreaming ? "Stop response" : "Send message", children: /* @__PURE__ */ jsx9("span", { children: /* @__PURE__ */ jsx9(
2061
+ !isMobile && renderSttButton("stt-right"),
2062
+ isVoiceModeEligible && !showSendButton && renderVoiceModeButton("voice-right"),
2063
+ showSendButton && /* @__PURE__ */ jsx9(Tooltip2, { title: isStreaming ? "Stop response" : "Send message", children: /* @__PURE__ */ jsx9("span", { children: /* @__PURE__ */ jsx9(
2062
2064
  IconButton5,
2063
2065
  {
2064
2066
  onClick: isStreaming ? onStop || (() => {
@@ -8265,8 +8267,10 @@ var EnhancedMobileConversationsModal = ({
8265
8267
  // Keep in sync with MOBILE_CONVERSATIONS_DRAWER_WIDTH in chat.tsx
8266
8268
  // (the chat shell translates by the same amount).
8267
8269
  width: "min(calc(100vw - 56px), 360px)",
8268
- // top/bottom stretch instead of 100dvh — iOS standalone
8269
- // under-reports dvh, leaving a dead band above the home bar.
8270
+ // Explicit 100lvh overflows iOS standalone's under-reported
8271
+ // viewport downward — bottom-anchoring alone stops short.
8272
+ height: "100dvh",
8273
+ "@supports (height: 100lvh)": { height: "100lvh" },
8270
8274
  bgcolor: theme.palette.background.paper,
8271
8275
  display: "flex",
8272
8276
  flexDirection: "column",
@@ -11233,18 +11237,20 @@ var ChatContent = () => {
11233
11237
  sx: (theme) => ({
11234
11238
  display: "flex",
11235
11239
  flexDirection: "column",
11236
- // Stretch via top/bottom instead of 100dvh — the iOS standalone
11237
- // webview under-reports dvh and left a dead band above the home
11238
- // indicator; inset-stretched fixed elements get the real viewport.
11240
+ // iOS standalone under-reports both dvh AND the fixed-position
11241
+ // containing block, stranding a dead band above the home bar.
11242
+ // An explicit 100lvh height can overflow that short viewport
11243
+ // downward, which bottom-anchoring cannot.
11239
11244
  overflow: "hidden",
11240
11245
  bgcolor: theme.palette.chat.shell,
11241
11246
  color: theme.palette.text.primary,
11242
11247
  position: "fixed",
11243
11248
  top: 0,
11244
11249
  bottom: 0,
11250
+ height: "100dvh",
11251
+ "@supports (height: 100lvh)": { height: "100lvh" },
11245
11252
  left: drawerOpen && !isMobile ? "340px" : 0,
11246
11253
  width: !isMobile && canvasOpen ? `calc(100vw - ${drawerOpen ? "340px" : "0px"} - ${CANVAS_WIDTH})` : drawerOpen && !isMobile ? "calc(100vw - 340px)" : "100vw",
11247
- zIndex: 0,
11248
11254
  // Claude-style push (mobile only; desktop stays flush): the chat
11249
11255
  // shell slides right as a full-height rounded card — exactly like
11250
11256
  // Claude iOS, where the card runs edge-to-edge vertically and the
@@ -11255,15 +11261,20 @@ var ChatContent = () => {
11255
11261
  // status area, the bottom stays flush with the screen edge, and the
11256
11262
  // motion reads as the native sheet-behind effect instead of the
11257
11263
  // content lurching downward.
11258
- transform: isMobile && mobileConversationsOpen ? "translateX(min(calc(100vw - 56px), 360px)) scale(0.93)" : "none",
11264
+ // Slides 12px OVER the drawer's edge (not edge-to-edge) and rides
11265
+ // above it in z-order, so the card's shadow falls on the drawer —
11266
+ // the overlapped-sheet look.
11267
+ transform: isMobile && mobileConversationsOpen ? "translateX(calc(min(calc(100vw - 56px), 360px) - 12px)) scale(0.93)" : "none",
11259
11268
  transformOrigin: "left bottom",
11260
11269
  borderRadius: isMobile && mobileConversationsOpen ? "36px" : 0,
11270
+ zIndex: isMobile && mobileConversationsOpen ? theme.zIndex.modal + 1 : 0,
11261
11271
  // Hairline border so the rounded card reads even when the backdrop
11262
11272
  // is the same near-black as the shell.
11263
11273
  border: isMobile && mobileConversationsOpen ? `1px solid ${theme.palette.mode === "dark" ? "rgba(255,255,255,0.14)" : "rgba(0,0,0,0.12)"}` : "none",
11264
11274
  boxShadow: isMobile && mobileConversationsOpen ? `0 12px 40px ${theme.palette.mode === "dark" ? "rgba(0,0,0,0.55)" : "rgba(0,0,0,0.25)"}` : "none",
11265
11275
  transition: "left 0.3s ease-in-out, width 0.3s ease-in-out, transform 0.3s ease-in-out, border-radius 0.3s ease-in-out"
11266
11276
  }),
11277
+ onClick: isMobile && mobileConversationsOpen ? () => setMobileConversationsOpen(false) : void 0,
11267
11278
  children: [
11268
11279
  /* @__PURE__ */ jsx23(
11269
11280
  chat_app_bar_default,
@@ -11368,7 +11379,10 @@ var ChatContent = () => {
11368
11379
  px: isMobile ? 1 : 2,
11369
11380
  // Reduce padding on mobile for better width utilization
11370
11381
  pb: logoOnly ? 0 : `${inputHeight + 24}px`,
11371
- maxHeight: isMobile ? "calc(var(--vh, 1vh) * 100)" : "100%",
11382
+ // The flex column already bounds this; the old --vh cap (from
11383
+ // window.innerHeight) under-measured in iOS standalone and let
11384
+ // the composer's auto margins float it above the bottom.
11385
+ maxHeight: "100%",
11372
11386
  WebkitOverflowScrolling: "touch",
11373
11387
  overscrollBehavior: "contain",
11374
11388
  position: "relative",
@@ -11494,7 +11508,7 @@ var ChatContent = () => {
11494
11508
  display: "flex",
11495
11509
  flexDirection: "column",
11496
11510
  alignItems: "center",
11497
- margin: "auto",
11511
+ margin: "0 auto",
11498
11512
  width: "100vw",
11499
11513
  maxWidth: "768px"
11500
11514
  },
@@ -11570,4 +11584,4 @@ var chat_default = Chat;
11570
11584
  export {
11571
11585
  chat_default
11572
11586
  };
11573
- //# sourceMappingURL=chunk-72TR4XAJ.mjs.map
11587
+ //# sourceMappingURL=chunk-LDGJKNI4.mjs.map